//指针定义:  指示变化位的数据模板
//    比如: [3,2,0]，表示第3，2，0位会发生变化，可以去看看手机app游戏"太极迷阵"，玩了后你就理解了
//    对于这就是江湖九华地宫， 指针是固定为[2,1,0]的

//归一化棋盘:
//    有些棋盘的处理是类似的，比如象棋里的上下翻转，左右翻转。为了减少处理的状态量，对棋盘进行了归一化处理。
//    然后比较节点时通过归一化值来比较。


//getpoint:
//从0/1字符串里构造指针,比如: 111构造为[2,1,0],  101构造为[2,0]
//对于这就是江湖九华地宫，输入固定为111，也就是指针固定为[2,1,0],  其它值请参见手机app游戏"太极迷阵"
getPoint = function(pointString)
{
   let point = []
   for (let i = pointString.length - 1; i >= 0; i--)
   {
       if (pointString[i] != '0') {
           point.push(i);
       }
   }
   return point
}

function CandleFactory(pointString) { //点亮蜡烛
    baseNode.call(this);
    this.board = []; //棋盘描述
    this.normalize = []; //归一化棋盘
    this.point = getPoint(pointString); //指针
}

// 设置原型链
CandleFactory.prototype = Object.create(baseNode.prototype);
CandleFactory.prototype.constructor = CandleFactory;

//提供的循环位移棋盘的功能
CandleFactory.prototype.shiftBoard = function(board) {
    if (board.length === 0) {
        return board; // 如果数组为空，直接返回
    }
    // 取出第一个元素
    const firstElement = board[0];
    // 获取除了第一个元素之外的所有元素组成的新数组
    const remainingArray = board.slice(1);
    // 将第一个元素添加到剩余数组的末尾
    const newBoard = remainingArray.concat(firstElement);
    return newBoard;
}

//提供的归一化棋盘的功能
//0和1组成的序列中，如果保证各个位不会出现交换，那么对于位移形成的序列，都是相等的
//那么从中找到最小值的那个作为代表，称为归一化值
CandleFactory.prototype.normalizeBoard = function(_board)
{   
    let board_size = _board.length;
    let b = _board;
    for (let i = 0; i < board_size; i++)
    {
        b = this.shiftBoard(b);
        if (b < _board) { //这里比较两个数组，貌似有问题，但似乎问题不大，好像也正常工作，暂时不改
            _board = b;
        }
    }
    return _board
}

//执行翻转功能
//根据指针points和索引index进行翻转
CandleFactory.prototype.turnBoard = function(boardArray, points, index) {
    const boardSize = boardArray.length;
 
    for (let p = 0; p < points.length; p++) {
        let pos = points[p] + index;
        pos = (pos % boardSize + boardSize) % boardSize; // 处理负数索引和大于boardSize的索引
 
        // 切换boardArray[pos]的值
        boardArray[pos] = boardArray[pos] === '0' ? '1' : '0';
    }
    return boardArray;
}

//拷贝节点
CandleFactory.prototype.CopyFrom = function(node)
{
    this.board = node.board.slice();
    this.normalize = node.normalize;
}

//初始化棋盘
CandleFactory.prototype.initBoard = function(_board)
{
    if (_board.length = 0) {
        return false;
    }
    for (ch of _board)
    {
        if (ch != '0' && ch != '1') {
            return false;
        }
    }
    this.board = [..._board];
    this.normalize = this.normalizeBoard(this.board);
    return true;
}

//获取该节点的所有变化节点
CandleFactory.prototype.getNextStates = function()
{
    let states = []
    let size = this.board.length;
    let log = this.board.join('') + '->';
    for (let i = 0; i < size; i++)
    {
        let new_state = new CandleFactory(this.point);
        new_state.CopyFrom(this)
        new_state.board = this.turnBoard(new_state.board, this.point, i);
        new_state.actionDesc = i.toString(); //动作描述，在这里定义为‘对特定位置进行翻转’
        new_state.normalize = this.normalizeBoard(new_state.board);
        new_state.point = this.point;
        states.push(new_state);
        log += new_state.board.join('') + ',';
    }
    console.log(log)
    return states;
}

//判断两个节点是否相等
CandleFactory.prototype.equal = function(node)
{
    //对归一化值进行比较
    return (this.normalize.join() == node.normalize.join());
}

//
CandleFactory.prototype.dump = function()
{
    let info = this.actionDesc + " : ";
    info += this.board.join('') + " / ";
    info += this.normalize.join('');
    return info;
}

//获得唯一标识
CandleFactory.prototype.id = function() {
    return this.normalize.join();
}